﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Linq;
using System.Xml.Serialization;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using BrainTechLLC.ThreadSafeObjects;
using WordsMatching;
using System.Collections.ObjectModel;
using Mud.EmlenMudMain;
using System.Text;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
#if NO_SILVERLIGHT
    [Browsable(true)]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    [EditorBrowsable(EditorBrowsableState.Always)]
#endif
    [Serializable]
    [DataContract]
    public partial class GameLocation : GameThingBaseClass, IGameThing, IHasPropertyData, INotifyPropertyChanged, INotifyPropertyChanging, INotifyCollectionChanged, ICanSaveAndRestore
    {        
        [DataMember]
        public string _areaName;

        [DataMember]
        public int _coins;

        [DataMember]
        public SectorType _sectorType;

        [DataMember]
        public RoomFlags _roomFlags;

        [DataMember, NonSerialized]
        public int _vnum;

        [DataMember]
        public LocationInt _XYZ;

        [DataMember]
        public long[] _edgeIDs;

        [DataMember]
        public AssociatedIDCollection _things;

        // [DataMember]
        [NonSerialized, XmlIgnore]
        public object _terrainAtLocation;

        [NonSerialized, XmlIgnore]
        public LocationEdge[] _edges;

        [DataMember]
        public string _roomDescription;

        [DataMember]
        public AssociatedIDCollection _resets;

        [DataMember]
        public List<NameAndDescription> _extraDescriptions;

        public bool IsRoomFlagSet(RoomFlags rf) { return ((RoomFlags & rf) != 0); }
        public bool IsRoomFlagSet(long rf) { return ((RoomFlags & (RoomFlags)rf) != 0); }

        public static GameLocation FindLocationByVnum(int vnum, Dictionary<int, GameLocation> dict)
        {
            GameLocation l;

            if (dict.TryGetValue(vnum, out l))
                return l;

            return null;
        }

        [XmlIgnore]
        public string RoomDescription
        {
            get { return _roomDescription == null ? string.Empty : _roomDescription; }
            set
            {
                if (!_roomDescription.AreEqual(value))
                {
                    OnPropertyChanging("RoomDescription", _roomDescription, value);
                    _roomDescription = value;
                    OnPropertyChanged("RoomDescription", _roomDescription, value);
                };
            }
        }

        [XmlIgnore]
        public List<NameAndDescription> ExtraDescriptions
        {
            get
            {
                if (_extraDescriptions == null)
                    Interlocked.CompareExchange<List<NameAndDescription>>(ref _extraDescriptions, new List<NameAndDescription>(), null);

                return _extraDescriptions;
            }
            set
            {
                if (!_extraDescriptions.AreEqual(value))
                {
                    OnPropertyChanging("ExtraDescriptions", _extraDescriptions, value);
                    _extraDescriptions = value;
                    OnPropertyChanged("ExtraDescriptions", _extraDescriptions, value);
                };
            }
        }

        [XmlIgnore]
        public bool HasResets
        {
            get { return _resets != null && _resets.Count > 0; }
        }

        [XmlIgnore]
        public AssociatedIDCollection Resets
        {
            get
            {
                if (_resets == null)
                    Interlocked.CompareExchange<AssociatedIDCollection>(ref _resets, new AssociatedIDCollection(), null);

                return _resets;
            }
        }

        [XmlIgnore]
        public int Vnum
        {
            get { return _vnum; }
            set
            {
                if (!_vnum.AreEqual(value))
                {
                    OnPropertyChanging("Vnum", _vnum, value);
                    _vnum = value;
                    OnPropertyChanged("Vnum", _vnum, value);
                };
            }
        }

        [XmlIgnore]
        public RoomFlags RoomFlags
        {
            get { return _roomFlags; }
            set
            {
                if (!_roomFlags.AreEqual(value))
                {
                    OnPropertyChanging("RoomFlags", _roomFlags, value);
                    _roomFlags = value;
                    OnPropertyChanged("RoomFlags", _roomFlags, value);
                };
            }
        }

        [XmlIgnore]
        public SectorType SectorType
        {
            get { return _sectorType; }
            set
            {
                if (!_sectorType.AreEqual(value))
                {
                    OnPropertyChanging("SectorType", _sectorType, value);
                    _sectorType = value;
                    OnPropertyChanged("SectorType", _sectorType, value);
                };
            }
        }

        public override string ToString()
        {
            return ShortName.EmptyIfNull() + " (" + _areaName.EmptyIfNull() + ")";
        }
        [XmlIgnore]
        public int Coins
        {
            get { return _coins; }
            set
            {
                if (!_coins.AreEqual(value))
                {
                    OnPropertyChanging("Coins", _coins, value);
                    _coins = value;
                    OnPropertyChanged("Coins", _coins, value);
                };
            }
        }

        [XmlIgnore]
        public LocationEdge this[GeneralDirection dir]
        {
            get
            {
                LocationEdge edge = Edges[(int)dir];
                return edge;
            }
        }

        [XmlIgnore]
        public string AreaName
        {
            get { return _areaName == null ? string.Empty : _areaName; }
            set
            {
                if (!_areaName.AreEqual(value))
                {
                    OnPropertyChanging("AreaName", _areaName, value);
                    _areaName = value;
                    OnPropertyChanged("AreaName", _areaName, value);
                };
            }
        }

        public override void PerformPostRestoreSetup()
        {
            base.PerformPostRestoreSetup();
            if (_edgeIDs != null)
            {
                for (int n = 0; n < _edgeIDs.Length; n++)
                {
                    long id = _edgeIDs[n];

                    // rethink - do we need to add these as dependencies?
                    //if (id > 0)
                    //    Dependencies.Add(id, null);
                }
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public long[] EdgeIDs
        {
            get
            {
                if (_edgeIDs == null)
                    Interlocked.CompareExchange<long[]>(ref _edgeIDs, new long[(int)GeneralDirection.Max], null);

                return _edgeIDs;
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public LocationEdge[] Edges
        {
            get
            {
                if (_edges == null)
                {
                    Interlocked.CompareExchange<LocationEdge[]>(ref _edges, new LocationEdge[(int)GeneralDirection.Max], null);
                    RecalculateEdges();
                }

                return _edges;
            }
        }

        public void RecalculateEdges()
        {
            if (_edgeIDs != null)
            {
                if (_edges == null)
                    Interlocked.CompareExchange<LocationEdge[]>(ref _edges, new LocationEdge[(int)GeneralDirection.Max], null);

                for (int n = 0; n < _edgeIDs.Length; n++)
                {
                    long id = _edgeIDs[n];

                    if (id > 0)
                        _edges[n] = Everything.Find<LocationEdge>(id);
                }
            }
        }

        public bool HasEdge(GeneralDirection dir)
        {
            return (Edges[(int)dir] != null);
        }

        public ObservableCollection<LocationEdge> ObservableLocationEdges
        {
            get
            {
                ObservableCollection<LocationEdge> result = new ObservableCollection<LocationEdge>();

                for (int n = 0; n < Edges.Length; n++)
                {
                    var edge = Edges[n];

                    if (edge != null)
                        result.Add(edge);
                }

                return result;
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public LocationInt XYZ
        {
            get
            {
                if (_XYZ == null)
                    Interlocked.CompareExchange<LocationInt>(ref _XYZ, new LocationInt(), null);

                return _XYZ;
            }
            set
            {
                if (!_XYZ.AreEqual(value))
                {
                    OnPropertyChanging("XYZ", _XYZ, value);
                    _XYZ = value;
                    OnPropertyChanged("XYZ", _XYZ, value);
                }
            }
        }

        public float FindByKeyword(string matchString, float threshold, out string matched, ref List<MatchAndStrength> matchedItems)
        {
            if (threshold == 0f)
                threshold = 0.55f;

            if (_things == null)
            {
                matched = string.Empty;
                matchedItems = null;
                return 0.0f;
            }
            return _things.FindByKeyword(matchString, threshold, out matched, ref matchedItems);
        }

        public string ShowText(ICanObserveViewable observer)
        {
            return ShowThings(observer).BuildList(Environment.NewLine, (s) => s);
        }

        public List<string> ShowThings(ICanObserveViewable observer)
        {
            List<string> results = new List<string>();
            results.Add(string.Format("{0} at {1},{2},{3}:", ShortName, XYZ.X, XYZ.Y, XYZ.Z));

            string exitString = string.Empty;
            for (int n = 0; n < (int)GeneralDirection.Max; n++)
            {
                if (Edges[n] != null)
                {
                    GameLocation locTo = Edges[n].ToGameLocation;

                    exitString += "[{B}" +
                        string.Format("{0} to {1},{2},{3}", ((GeneralDirection)n).ToString(), locTo.XYZ.X, locTo.XYZ.Y, locTo.XYZ.Z) +
                        "{N}] ";
                }
            }

            if (!string.IsNullOrEmpty(exitString))
                results.Add(exitString);

            List<IGameThing> things = _things.ReadItems<IGameThing>();
            for (int n = 0; n < things.Count; n++)
            {
                BaseClass thingBase = things[n] as BaseClass;
                if (thingBase != null)
                {
                    string s;
                    if (string.IsNullOrEmpty(thingBase.OneLineDescription))
                        s = observer.GetViewOf(thingBase, "ShortName", ViewType.See).GetPropertyValue(ViewType.See, true).ToString();
                    else
                        s = observer.GetViewOf(thingBase, "OneLineDescription", ViewType.See).GetPropertyValue(ViewType.See, true).ToString();

                    if (!string.IsNullOrEmpty(s))
                        results.Add(s);
                }
                else
                {
                    IHasNameAndDescription nameAndDesc = things[n] as IHasNameAndDescription;
                    if (nameAndDesc != null)
                    {
                        string s = nameAndDesc.ToString();
                        results.Add(s);
                    }
                }
            }

            if (_name != null && !string.IsNullOrEmpty(Name.Description))
            {
                results.Add(Name.Description);
            }

            return results;
        }

        [XmlIgnore]
        public ObservableCollection<object> ObservableThings
        {
            get { return Things.AllGameThingsInCollection.Cast<object>().ToObservable(); }
        }

        [XmlIgnore]
        public bool Indoors
        {
            get
            {
                return ((RoomFlags & BrainTechLLC.RoomFlags.INDOORS) != 0);
            }
            set
            {
                if (value == true) RoomFlags |= BrainTechLLC.RoomFlags.INDOORS;
                else RoomFlags &= (~(BrainTechLLC.RoomFlags.INDOORS));
            }
        }

        public bool IsDark()
        {
            if (ThingProperties.GetArgument<int>("LightingAmount") > 0) return false;
            if (IsRoomFlagSet(BrainTechLLC.RoomFlags.DARK)) return true;
            if (IsRoomFlagSet(BrainTechLLC.RoomFlags.INDOORS)) return false;
            if (SectorType == (long)BrainTechLLC.SectorType.INSIDE) return false;
            // TODO
            //if (DynamicWorld.WeatherInfo.Sunlight == TimeOfDayType.SUN_RISE ||
            //  DynamicWorld.WeatherInfo.Sunlight == TimeOfDayType.SUN_LIGHT ||
            //  DynamicWorld.WeatherInfo.Sunlight == TimeOfDayType.SUN_SET) return false;
            return true;
        }

        public string GetShortExitNameInDirection(GameChar chr, GeneralDirection dir)
        {
            StringBuilder sb = new StringBuilder(512);
            LocationEdge exitd = this[dir];
            if (exitd == null) return "";
            //if (CanSee(exitd) == false) return "";
            string szAdd = "";
            string szDirLetter = StaticHelpers.DirFirstLetterCap(dir);
            if (chr.ThingProperties.GetArgument<bool>("HolyLight"))
            {
                if (exitd.ToLocationId > 0 && exitd.ToGameLocation == null)
                {
                    szAdd = "(To missing location " + exitd.ToLocationId.ToString() + ")";
                }
                else
                {
                    LocationEdge exitLeadingIn = exitd.GetIncomingEdgeForOutgoingDirection(dir);
                    if (exitLeadingIn == null)
                    {
                        szAdd = "(One-way exit)";
                    }
                    else
                    {
                        if (exitLeadingIn.ToLocationId > 0 && (exitLeadingIn.ToGameLocation == null || exitLeadingIn.ToGameLocation.XYZ != this.XYZ))
                        {
                            if (exitLeadingIn.ToGameLocation == null)
                            {
                                szAdd = "(Reverse exits links to missing location " + exitLeadingIn.ToGameLocation.XYZ.ToString() + ")";
                            }
                            else
                            {
                                szAdd = "(Reverse exits links to location " + exitLeadingIn.ToLocationId.ToString() + ")";
                            }
                        }
                    }
                }
            }
            EdgeData door = null;

            if (exitd.HasEdgeData)
                door = exitd.EdgeData;

            if (door == null)
            {
                return szDirLetter + szAdd;
            }
            //else if (chr.CanSee(door) == false)
            //{
            //    return szAdd;
            //}
            else if (door.IsDoor)
            {
                return szDirLetter + "(" + door.DoorName + ", " + door.StatusString() + ")" +
                  szAdd;
            }
            else
            {
                return szDirLetter + szAdd;
            }
        }

        public StringBuilder HowRoomLooksTo(GameChar chrLooker)
        {
            StringBuilder sb = new StringBuilder(1024);

            // TODO
            //if (!chrLooker.CanSee(this))
            //{
            //    return GetReasonWhyCharacterCantSeeInRoom(chrLooker);
            //}

            sb.Append("{W}" + Name);
            if (chrLooker.ThingProperties.GetArgument<bool>("AutoExit"))
            {
                int nExits = 0;
                LocationEdge ex;
                for (int i = 0; i < (int)GeneralDirection.Max; i++)
                {
                    ex = Edges[i] as LocationEdge;
                    if (ex == null) continue;
                    //if (chrLooker.CanSee(ex) == false) continue;
                    if (nExits == 0) { sb.Append(" {G}["); }
                    else { sb.Append(", "); }
                    sb.Append(GetShortExitNameInDirection(chrLooker, (GeneralDirection)i));
                    nExits++;
                }
                if (nExits > 0) sb.Append("]");
            }
            sb.Append("{N}\n\r{w}" + RoomDescription);
            //if (moreRoomDetailsInternal != null)
            //{
            //    int k = 0;
            //    for (int i = 0; i < moreRoomDetailsInternal.CharactersInRoom.Count; i++)
            //    {
            //        CharacterData chVict = moreRoomDetailsInternal.CharactersInRoom[i];
            //        if (chrLooker == chVict) continue;
            //        if (chrLooker.CanSee(chVict) == true)
            //        {
            //            k++;
            //            sb.Append("{W}[" + k.ToString() + "]{w} " + chrLooker.ViewAsAppearsInRoom(chVict));
            //        }
            //    }
            //}

            return sb;
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public AssociatedIDCollection Things
        {
            get
            {
                if (_things == null)
                    Interlocked.CompareExchange<AssociatedIDCollection>(ref _things, new AssociatedIDCollection(), null);

                return _things;
            }
            set
            {
                if (!_things.AreEqual(value))
                {
                    OnPropertyChanging("Things", _things, value);
                    _things = value;
                    OnPropertyChanged("Things", _things, value);
                }
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public object TerrainAtLocation
        {
            get
            {
                return _terrainAtLocation;
            }
            set
            {
                if (!_terrainAtLocation.AreEqual(value))
                {
                    OnPropertyChanging("TerrainAtLocation", _terrainAtLocation, value);
                    _terrainAtLocation = value;
                    OnPropertyChanged("TerrainAtLocation", _terrainAtLocation, value);
                }
            }
        }

        public override void RegisterChildrenForPropertyChangeEvents()
        {
            XYZ.PropertyChanged += new PropertyChangedEventHandler(XYZ_PropertyChanged);
#if NO_SILVERLIGHT
            XYZ.PropertyChanging += new PropertyChangingEventHandler(XYZ_PropertyChanging);
            Things.CollectionChanged += new NotifyCollectionChangedEventHandler(Things_CollectionChanged);
#else
            XYZ.PropertyChanging += new EventHandler<PropertyChangingEventArgsEx>(XYZ_PropertyChanging);
            // TODO: NOT WORKING ON SILVERLIGHT VERSION
            // Things.CollectionChanged += new EventHandler<NotifyCollectionChangedEventArgsEx<IdentifierAndValue>>(Things_CollectionChanged);
#endif
            base.RegisterChildrenForPropertyChangeEvents();
        }

#if NO_SILVERLIGHT
        void Things_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            OnCollectionChanged(sender, e);
        }

        void XYZ_PropertyChanging(object sender, PropertyChangingEventArgs e)
        {
            PropertyChangingEventArgsEx args = e as PropertyChangingEventArgsEx;
            OnPropertyChanging(sender, args);
        }
#else
        void Things_CollectionChanged(object sender, NotifyCollectionChangedEventArgsEx<IdentifierAndValue> e)
        {
            OnCollectionChanged(sender, e);
        }

        void XYZ_PropertyChanging(object sender, PropertyChangingEventArgsEx e)
        {
            OnPropertyChanging(sender, e);
        }
#endif

        void XYZ_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            PropertyChangedEventArgsEx args = e as PropertyChangedEventArgsEx;
            OnPropertyChanged(sender, args);
        }
    }

    public static class LocationExtens
    {
        [MethodVisible]
        public static LocationInt ParseLocationInt(this string location)
        {
            string[] strings = location.Split(",".ToCharArray());
            if (strings.Length >= 2)
            {
                int x = strings[0].TryInt();
                int y = strings[1].TryInt();
                int z = strings.StringOrEmpty(2).TryInt();

                return new LocationInt(x, y, z);
            }
            return null;
        }
        [MethodVisible]
        public static GameLocation ParseLocation(this string location)
        {
            string[] strings = location.Split(",".ToCharArray());
            if (strings.Length >= 2)
            {
                int x = strings[0].TryInt();
                int y = strings[1].TryInt();
                int z = strings.StringOrEmpty(2).TryInt();

                return WorldMap.Instance.World[x, y, z];
            }
            return null;
        }
    }


    [Serializable]
    [DataContract]
    public partial class EdgeData : GameThingBaseClass
    {
        public EdgeData() { }
        public bool FlagSet(ExitFlags nBitfield, ExitFlags nFlag) { return ((nBitfield & nFlag) != 0); }
        public bool FlagSet(ExitFlags nFlag) { return ((ExitFlags & (int)nFlag) != 0); }

        [DataMember]
        public int _exitFlags;	/* Exit flags, mostly compat with diku */

        [XmlIgnore]
        public int ExitFlags
        {
            get { return _exitFlags; }
            set
            {
                if (!_exitFlags.AreEqual(value))
                {
                    OnPropertyChanging("ExitFlags", _exitFlags, value);
                    _exitFlags = value;
                    OnPropertyChanged("ExitFlags", _exitFlags, value);
                };
            }
        }

        [DataMember]
        public long _key;		/* Key required to open the door */

        [XmlIgnore]
        public long Key
        {
            get { return _key; }
            set
            {
                if (!_key.AreEqual(value))
                {
                    OnPropertyChanging("Key", _key, value);
                    _key = value;
                    OnPropertyChanged("Key", _key, value);
                };
            }
        }

        [XmlIgnore]
        public string Keyword /* keyword for exit description */
        {
            get { return this.Keywords; }
            set
            {
                Name.Keywords = value;
            }
        }

        [XmlIgnore]
        public string Description /* Exit description */
        {
            get { return this.Description; }
            set { Name.Description = value; }
        }

        [XmlIgnore]
        public int MaxStrength /* Maximum door strength */
        {
            get { return ThingProperties.GetArgument<int>("MaxStrength"); }
            set { AddOrSetProperty("MaxStrength", value); }
        }

        [XmlIgnore]
        public int CurrentStrength /* Door strength */
        {
            get { return ThingProperties.GetArgument<int>("CurrentStrength"); }
            set { AddOrSetProperty("CurrentStrength", value); }
        }

        [DataMember]
        public int _resetExitFlags;	/* Reset Flags for doors, etc */

        [XmlIgnore]
        public int ResetExitFlags
        {
            get { return _resetExitFlags; }
            set
            {
                if (!_resetExitFlags.AreEqual(value))
                {
                    OnPropertyChanging("ResetExitFlags", _resetExitFlags, value);
                    _resetExitFlags = value;
                    OnPropertyChanged("ResetExitFlags", _resetExitFlags, value);
                };
            }
        }

        [XmlIgnore]
        public string DoorName
        {
            get { if (string.IsNullOrEmpty(this.ShortName)) return "door"; else return ShortName; }
            set
            {
                if (_name == null && string.IsNullOrEmpty(value))
                    return;

                ShortName = value;
            }
        }

        public string StatusString()
        {
            if (FlagSet(BrainTechLLC.ExitFlags.CLOSED)) return "closed";
            return "open";
        }

        [XmlIgnore]
        public bool IsDoor
        {
            get { return ((ExitFlags & (int)BrainTechLLC.ExitFlags.ISDOOR) != 0); }
            set
            {
                if ((ExitFlags & (int)BrainTechLLC.ExitFlags.ISDOOR) == 0)
                {
                    if (value == true) { ExitFlags |= (int)BrainTechLLC.ExitFlags.ISDOOR; }
                }
                else
                {
                    if (value == false) { ExitFlags &= (~((int)BrainTechLLC.ExitFlags.ISDOOR)); }
                }
            }
        }
    }

    [Serializable]
    [DataContract]
    public class Reset : BaseClass
    {
        public Reset() { }

        [DataMember]
        public char _command;	/* command (Object Mob, etc) */

        [XmlIgnore]
        public char Command
        {
            get { return _command; }
            set
            {
                if (!_command.AreEqual(value))
                {
                    OnPropertyChanging("Command", _command, value);
                    _command = value;
                    OnPropertyChanged("Command", _command, value);
                };
            }
        }

        [DataMember]
        public long _gameLocationID;

        [XmlIgnore]
        public long GameLocationID
        {
            get { return _gameLocationID; }
            set
            {
                if (!_gameLocationID.AreEqual(value))
                {
                    OnPropertyChanging("GameLocationID", _gameLocationID, value);
                    _gameLocationID = value;
                    OnPropertyChanged("GameLocationID", _gameLocationID, value);
                };
            }
        }

        [DataMember]
        public int _resetVnum;

        [XmlIgnore]
        public int ResetVnum
        {
            get { return _resetVnum; }
            set
            {
                if (!_resetVnum.AreEqual(value))
                {
                    OnPropertyChanging("ResetVnum", _resetVnum, value);
                    _resetVnum = value;
                    OnPropertyChanged("ResetVnum", _resetVnum, value);
                };
            }
        }

        [DataMember]
        public int _applyEffectLocation;		/* ApplyEffectLocation or amount for shopkeeprs */

        [XmlIgnore]
        public int ApplyEffectLocation
        {
            get { return _applyEffectLocation; }
            set
            {
                if (!_applyEffectLocation.AreEqual(value))
                {
                    OnPropertyChanging("ApplyEffectLocation", _applyEffectLocation, value);
                    _applyEffectLocation = value;
                    OnPropertyChanged("ApplyEffectLocation", _applyEffectLocation, value);
                };
            }
        }

        [DataMember]
        public int _percent;	/* Percent chance of pop */

        [XmlIgnore]
        public int Percent
        {
            get { return _percent; }
            set
            {
                if (!_percent.AreEqual(value))
                {
                    OnPropertyChanging("Percent", _percent, value);
                    _percent = value;
                    OnPropertyChanged("Percent", _percent, value);
                };
            }
        }

        [DataMember]
        public int _inRoomVnum;		/* VnumRoom it pops */

        [XmlIgnore]
        public int InRoomVnum
        {
            get { return _inRoomVnum; }
            set
            {
                if (!_inRoomVnum.AreEqual(value))
                {
                    OnPropertyChanging("InRoomVnum", _inRoomVnum, value);
                    _inRoomVnum = value;
                    OnPropertyChanged("InRoomVnum", _inRoomVnum, value);
                };
            }
        }

        [DataMember]
        public long _popsAssociatedID;

        [XmlIgnore]
        public long PopsAssociatedID
        {
            get { return _popsAssociatedID; }
            set
            {
                if (!_popsAssociatedID.AreEqual(value))
                {
                    OnPropertyChanging("PopsAssociatedID", _popsAssociatedID, value);
                    _popsAssociatedID = value;
                    OnPropertyChanged("PopsAssociatedID", _popsAssociatedID, value);
                };
            }
        }        
    }

}